Skip to content

Conversation

@ypatil12
Copy link
Collaborator

@ypatil12 ypatil12 commented Jan 8, 2026

Motivation:

Address findings from the Certora audit of EigenLayer Slashing UX Improvements. This branch consolidates fixes for low-severity findings (L-01) and informational findings (I-01 through I-05) across AllocationManager and ProtocolRegistry contracts.

Modifications:

AllocationManager Fixes

L-01: State inconsistency fixes

I-01: Re-proposing same pending slasher is now a no-op (#1689)

  • Added check in _updateSlasher() to skip processing if the proposed slasher is already pending
  • Prevents accidentally restarting the delay countdown

I-02: Add NatSpec documentation for getSlasher/getPendingSlasher (#1689)

  • Document that these functions return address(0)/0 for non-existent operator sets

I-03: Add separate SLASHER_CONFIGURATION_DELAY constant (#1689)

  • New immutable allows independent configuration of slasher delay in future upgrades
  • Currently set to same value as ALLOCATION_CONFIGURATION_DELAY

I-05: Add gas warning documentation for migrateSlashers (#1689)

  • Document O(appointees) gas cost per operator set
  • Warn about potential block gas limit issues with large appointee sets

ProtocolRegistry Fixes

I-01: ship() lacks validation (#1690)

  • Added array length validation for addresses, configs, and names
  • Added zero address validation with new ArrayLengthMismatch() and InputAddressZero() errors

I-02: Orphaned configs on name overwrite (#1690)

  • Delete old address's DeploymentConfig when re-shipping a name with a new address
  • Added DeploymentConfigDeleted(address) event

I-03: configure() for unshipped addresses (#1690)

  • Updated configure to require a name parameter
  • Added validation that address must be a shipped deployment

I-04: Fix misleading NatSpec (#1690)

  • Clarified ship() behavior when re-shipping names
  • Updated configure() NatSpec for address requirements

I-05: Document pauseAll blocking (#1690)

  • Added warning that pauseAll() reverts if ANY pausable deployment fails

Other Changes

Result:

  • Audit fixes complete

ypatil12 and others added 6 commits January 8, 2026 14:11
**Motivation:**

Claude Code is an AI-powered CLI tool that can assist with development
tasks. Adding project-specific skills and instructions helps Claude
understand EigenLayer conventions and automate common workflows like
writing tests, extracting audit findings, and formatting interfaces.

**Modifications:**

- Add 4 Claude Code skills in `.claude/skills/`:
- `audit-extractor`: Extract findings from PDF audit reports to markdown
checklists
- `integration-test-writer`: Write Solidity integration tests following
project conventions
- `interface-lint`: Format and lint Solidity interfaces with proper
documentation
- `unit-test-writer`: Write Solidity unit tests with per-function test
contracts
- Add `CLAUDE.md` with project-specific instructions, build commands,
and conventions
- Add slashing UX improvements audit report PDF and extracted findings
markdown

**Result:**

Developers using Claude Code will have access to specialized skills that
follow EigenLayer's testing and documentation conventions, improving
productivity and code consistency.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
**Motivation:**

Minor updates to the upgrade script for testnet deploy

**Modifications:**

Update condition on whether to *not* continue upgrade. Previously was
hitting a zeus env var not found error.
 
**Result:**

Working upgrade scripts
…1687)

**Motivation:**

Address L-01 finding from the Certora audit: "Instant slasher setting
leaves stale slasher field in storage". When `_updateSlasher()` is
called with `instantEffectBlock=true`, only `pendingSlasher` and
`effectBlock` are updated, leaving the `slasher` field stale (address(0)
for new operator sets). While `getSlasher()` returns correct values, raw
storage is inconsistent.

**Modifications:**

- Updated `_updateSlasher()` in `AllocationManager.sol` to set
`params.slasher = slasher` when `instantEffectBlock=true`
- Updated NatSpec for `SlasherParams` struct in `IAllocationManager.sol`
to document storage behavior
- Added `getSlasherParams()` helper to `AllocationManagerHarness.sol`
for testing raw storage
- Added unit tests for instant slasher storage consistency
- Updated documentation in `docs/core/AllocationManager.md`

**Result:**

- Storage is now consistent when creating operator sets or migrating
slashers
- Both `slasher` and `pendingSlasher` fields are set immediately when
`instantEffectBlock=true`
- Raw storage reads will return expected values matching `getSlasher()`
return value

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…operators (#1688)

**Motivation:**

Addresses audit finding **L-01: State inconsistency for new operator
allocation delay**. When a new operator registers through
DelegationManager, their allocation delay is set via
`_setAllocationDelay(..., newlyRegistered=true)`. Previously, only
`pendingDelay` and `effectBlock` were updated, leaving `delay` and
`isSet` at default values until applied. This created temporary storage
inconsistency.

**Modifications:**

- `AllocationManager._setAllocationDelay()`: When
`newlyRegistered=true`, now also sets `info.delay = delay` and
`info.isSet = true` for immediate storage consistency
- `IAllocationManager`: Updated NatSpec for `AllocationDelayInfo` struct
to document the immediate update behavior
- `AllocationManagerHarness`: Added `getAllocationDelayInfoRaw()`
function for testing raw storage values
- Unit tests: Added
`test_setAllocationDelay_newlyRegistered_setsDelayAndIsSetImmediately`
and `test_setAllocationDelay_existingOperator_delayNotSetImmediately`
- Documentation: Updated `setAllocationDelay` Effects section in
`docs/core/AllocationManager.md`

**Result:**

Raw storage in `_allocationDelayInfo[operator]` now correctly reflects
the effective allocation delay immediately for newly registered
operators. The `getAllocationDelay()` view function behavior remains
unchanged (it already returned correct values by applying pending values
in-memory).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…1689)

**Motivation:**

Address informational findings from the Certora audit of EigenLayer
Slashing UX Improvements (PR-1645/PR-544). These are quality-of-life and
documentation improvements that enhance code clarity and prevent
potential edge case issues.

**Modifications:**

1. **Fix I-01: Re-proposing same pending slasher is now a no-op**
- Added check in `_updateSlasher()` to skip processing if the proposed
slasher is already pending and hasn't taken effect
- Prevents accidentally restarting the delay countdown when re-proposing
the same slasher

2. **Fix I-02: Add NatSpec documentation for
getSlasher/getPendingSlasher**
- Updated interface and implementation NatSpec to document that these
functions return `address(0)`/`0` for non-existent operator sets
   - Helps callers understand expected behavior without validation

3. **Fix I-03: Add separate SLASHER_CONFIGURATION_DELAY constant**
- Added new `SLASHER_CONFIGURATION_DELAY` immutable in
`AllocationManagerStorage`
- Currently set to same value as `ALLOCATION_CONFIGURATION_DELAY` but
can be changed independently in future upgrades
   - Updated `_updateSlasher()` to use the new constant
   - Added interface getter

4. **Fix I-05: Add gas warning documentation for migrateSlashers**
   - Added NatSpec warning about O(appointees) gas cost per operator set
- `PermissionController.getAppointees()` enumerates full appointee set
which can be expensive
- Documented that large appointee sets may cause block gas limit issues

**Result:**

- `updateSlasher` is idempotent when re-proposing the same slasher
- Clearer documentation on view function return values
- Slasher delay can be configured independently in future upgrades
- Users are warned about potential gas issues with `migrateSlashers`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
**Motivation:**

Address informational findings from the Certora audit for Protocol
Registry (PR-1655). These improvements enhance validation, prevent
potential issues with orphaned configurations, and improve documentation
clarity.

**Modifications:**

1. **Fix I-01: ship() lacks validation**
- Added array length validation: `addresses.length == configs.length ==
names.length`
- Added zero address validation: revert if any address is `address(0)`
   - Added new errors: `ArrayLengthMismatch()` and `InputAddressZero()`

2. **Fix I-02: Orphaned configs on name overwrite**
- When re-shipping a name with a new address, the old address's
`DeploymentConfig` is now deleted
   - Added `DeploymentConfigDeleted(address)` event to signal cleanup
   - Prevents orphaned configs that could cause confusion

3. **Fix I-03: configure() for unshipped addresses**
   - Update `configure` function to pass in a name
- Added validation that the address must be a shipped deployment before
allowing configuration

5. **Fix I-04: Fix misleading NatSpec**
- Updated `ship()` NatSpec to document that names can be re-shipped with
new addresses
- Clarified that old address configs are automatically deleted when this
happens
- Updated `configure()` NatSpec to indicate address must be previously
shipped

6. **Fix I-05: Document pauseAll blocking**
- Added warning documentation that `pauseAll()` will revert if ANY
pausable deployment fails
- A single misconfigured deployment can block the entire protocol pause
   - Important for operational awareness during emergency scenarios

**Result:**

- `ship()` validates inputs before processing
- No more orphaned configs when re-shipping names
- `configure()` only works for shipped addresses
- Clearer documentation on expected behavior and edge cases
- Operators understand risks of `pauseAll()` failure scenarios

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
@ypatil12 ypatil12 force-pushed the release-dev/slashing-improvements-audit-fixes branch from e4af766 to d300f6d Compare January 8, 2026 19:11
**Motivation:**

The `ship()` function in ProtocolRegistry currently allows empty strings
to be passed as contract names. Empty names are semantically meaningless
and could lead to confusing registry state or lookup failures.

**Modifications:**

- Added `InputNameEmpty()` error to `IProtocolRegistryErrors` interface
- Added validation in `ship()` to reject empty contract names with
`require(bytes(names[i]).length > 0, InputNameEmpty())`
- Added unit test `test_ship_revert_emptyName()` to verify the
validation
- Updated documentation to reflect the non-empty name requirement
- Regenerated Go bindings

**Result:**

Calling `ship()` with an empty string in the `names` array will now
revert with `InputNameEmpty()`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Member

@0xClandestine 0xClandestine left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@ypatil12 ypatil12 merged commit 80b74fa into main Jan 13, 2026
20 checks passed
@ypatil12 ypatil12 deleted the release-dev/slashing-improvements-audit-fixes branch January 13, 2026 17:45
@ypatil12 ypatil12 restored the release-dev/slashing-improvements-audit-fixes branch January 13, 2026 17:45
@github-actions
Copy link

Certora Run Started (Verified Rules)

  • Group ID: f2280f01-d5b7-4f47-a5ec-c21292083049
Config Status Link Log File
core/AllocationManager.conf Failed (1) - certora/confs/core/AllocationManager.conf-05e1cb96ce6d.log
core/AllocationManagerOverslashing.conf Failed (1) - certora/confs/core/AllocationManagerOverslashing.conf-dabd0bc6b6a9.log
core/AllocationManagerSanity.conf Compiled - certora/confs/core/AllocationManagerSanity.conf-79c9b88c603e.log
core/AllocationManagerValidState.conf Failed (1) - certora/confs/core/AllocationManagerValidState.conf-dddda42637d6.log
core/DelegationManager.conf Compiled - certora/confs/core/DelegationManager.conf-ed2e4ad2af4a.log
core/DelegationManagerValidState.conf Compiled - certora/confs/core/DelegationManagerValidState.conf-7a4ce7345db0.log
core/StrategyManager.conf Compiled - certora/confs/core/StrategyManager.conf-7719b889fbcd.log
multichain/BN254CertificateVerifier.conf Compiled - certora/confs/multichain/BN254CertificateVerifier.conf-5bcd34b20c9e.log
multichain/CrossChainRegistry.conf Failed (1) - certora/confs/multichain/CrossChainRegistry.conf-6fb5961a17ce.log
multichain/ECDSACertificateVerifier.conf Compiled - certora/confs/multichain/ECDSACertificateVerifier.conf-81337c010fd2.log
multichain/KeyRegistrar.conf Compiled - certora/confs/multichain/KeyRegistrar.conf-0552d60ec11c.log
multichain/OperatorTableUpdater.conf Failed (1) - certora/confs/multichain/OperatorTableUpdater.conf-b7284ecea2a0.log
permissions/Pausable.conf Compiled - certora/confs/permissions/Pausable.conf-95ae9a75ef4c.log
pods/EigenPodManagerRules.conf Compiled - certora/confs/pods/EigenPodManagerRules.conf-90ae1f86c977.log
strategies/StrategyBase.conf Compiled - certora/confs/strategies/StrategyBase.conf-5ebacbe48e78.log

Certora Run Summary

  • Started 0 jobs
  • 5 jobs failed

Download Logs

@github-actions
Copy link

Certora Run Started (Verified Rules)

  • Group ID: 2eb444e7-87db-42ef-940f-ce7551420c6f
Config Status Link Log File
core/AllocationManager.conf Failed (1) - certora/confs/core/AllocationManager.conf-99d7937c4457.log
core/AllocationManagerOverslashing.conf Failed (1) - certora/confs/core/AllocationManagerOverslashing.conf-75db763ec61e.log
core/AllocationManagerSanity.conf Compiled - certora/confs/core/AllocationManagerSanity.conf-1971a2aab10e.log
core/AllocationManagerValidState.conf Failed (1) - certora/confs/core/AllocationManagerValidState.conf-a8ac45fcf1e2.log
core/DelegationManager.conf Compiled - certora/confs/core/DelegationManager.conf-59df2c1a797f.log
core/DelegationManagerValidState.conf Compiled - certora/confs/core/DelegationManagerValidState.conf-460cf662294d.log
core/StrategyManager.conf Compiled - certora/confs/core/StrategyManager.conf-2400ec81e87f.log
multichain/BN254CertificateVerifier.conf Compiled - certora/confs/multichain/BN254CertificateVerifier.conf-0470959ea9b6.log
multichain/CrossChainRegistry.conf Failed (1) - certora/confs/multichain/CrossChainRegistry.conf-ca13f9eec39d.log
multichain/ECDSACertificateVerifier.conf Compiled - certora/confs/multichain/ECDSACertificateVerifier.conf-606e150fcd24.log
multichain/KeyRegistrar.conf Compiled - certora/confs/multichain/KeyRegistrar.conf-a64d23b97981.log
multichain/OperatorTableUpdater.conf Failed (1) - certora/confs/multichain/OperatorTableUpdater.conf-4662e73d923a.log
permissions/Pausable.conf Compiled - certora/confs/permissions/Pausable.conf-7cade0e8d48e.log
pods/EigenPodManagerRules.conf Compiled - certora/confs/pods/EigenPodManagerRules.conf-93e226587e6d.log
strategies/StrategyBase.conf Compiled - certora/confs/strategies/StrategyBase.conf-d3767afbf20f.log

Certora Run Summary

  • Started 0 jobs
  • 5 jobs failed

Download Logs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants